package org.zjt.invoke;

import java.lang.invoke.*;
import java.util.Random;


// javac Circuit.java
// java Circuit
public class Circuit {

    public void println(Object value) {
        System.out.println("value=" + value);
    }

    /**
     * 向receiver绑定具体方法点
     * @param receiver
     * @return
     * @throws Throwable
     */
    public static MethodHandle getMethodHandle(Object receiver) throws Throwable {

        //如果Lookup对象
        MethodHandles.Lookup lookup = MethodHandles.lookup();

        //MethodType代表方法的类型(不包含方法名称)，其实MethodType是为了确定方法的描述符，例如此方法描述符为：(Ljava/lang/Object;)V
        MethodType methodType = MethodType.methodType(void.class, Object.class);


        //在接收者类中查找一个名为println，指定方法类型的虚方法
        return lookup.findVirtual(receiver.getClass(), "println", methodType).bindTo(receiver);
    }

    public static void startRace(Object arg) {

    }


    public static void main(String[] args) throws Throwable {
        Object receiver = new Random().nextInt(1000)%2==0 ? System.out : new Circuit();


        // 无论receiver最终是什么类型，只要有println方法，方法就可以正常调用。
        getMethodHandle(receiver).invoke("Hello Dynamic Invoke");
    }


}
